import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

import '../chat_core/theme/chat_theme.dart';
import 'utils/composer_action.dart';
import 'utils/composer_height_notifier.dart';
import 'utils/typedefs.dart';

/// The message composer widget positioned at the bottom of the chat screen.
///
/// Includes a text input field, an optional attachment button, and a send button.
class Composer extends StatefulWidget {
  /// Optional controller for the text input field.
  final TextEditingController? textEditingController;

  /// Optional left position.
  final double? left;

  /// Optional right position.
  final double? right;

  /// Optional top position.
  final double? top;

  /// Optional bottom position.
  final double? bottom;

  /// Optional X blur value for the background (if using glassmorphism).
  final double? sigmaX;

  /// Optional Y blur value for the background (if using glassmorphism).
  final double? sigmaY;

  /// Padding around the composer content.
  final EdgeInsetsGeometry? padding;

  /// 左侧操作按钮列表
  final List<ComposerAction>? leftActions;

  /// 右侧操作按钮列表
  final List<ComposerAction>? rightActions;

  /// Horizontal gap between elements (attachment icon, text field, send icon).
  final double? gap;

  /// Border style for the text input field.
  final InputBorder? inputBorder;

  /// Whether the text input field should be filled.
  final bool? filled;

  /// Optional widget to display above the main composer row.
  final Widget? topWidget;

  /// Whether to adjust padding for the bottom safe area.
  final bool? handleSafeArea;

  /// Background color of the composer container.
  final Color? backgroundColor;

  /// Color of the attachment icon.
  final Color? attachmentIconColor;

  /// Color of the send icon.
  final Color? sendIconColor;

  /// Color of the hint text in the input field.
  final Color? hintColor;

  /// Color of the text entered in the input field.
  final Color? textColor;

  /// Fill color for the text input field when [filled] is true.
  final Color? inputFillColor;

  /// Placeholder text for the input field.
  final String? hintText;

  /// Appearance of the keyboard.
  final Brightness? keyboardAppearance;

  /// Whether to enable autocorrect for the input field.
  final bool? autocorrect;

  /// Whether the input field should autofocus.
  final bool autofocus;

  /// Capitalization behavior for the input field.
  final TextCapitalization textCapitalization;

  /// Type of keyboard to display.
  final TextInputType? keyboardType;

  /// Action button type for the keyboard (e.g., newline, send).
  final TextInputAction? textInputAction;

  /// Focus node for the text input field.
  final FocusNode? focusNode;

  /// Maximum character length for the input field.
  final int? maxLength;

  /// Minimum number of lines for the input field.
  final int? minLines;

  /// Maximum number of lines the input field can expand to.
  final int? maxLines;

  /// 输入框的底部组件
  final Widget? bottomWidget;

  /// Creates the main chat widget.
  const Composer({
    super.key,
    this.textEditingController,
    this.left = 0,
    this.right = 0,
    this.top,
    this.bottom = 0,
    this.sigmaX = 20,
    this.sigmaY = 20,
    this.padding = const EdgeInsets.all(8.0),
    this.leftActions,
    this.rightActions,
    this.gap = 8,
    this.inputBorder = const OutlineInputBorder(
      borderSide: BorderSide.none,
      borderRadius: BorderRadius.all(Radius.circular(24)),
    ),
    this.filled = true,
    this.topWidget,
    this.handleSafeArea = true,
    this.backgroundColor,
    this.attachmentIconColor,
    this.sendIconColor,
    this.hintColor,
    this.textColor,
    this.inputFillColor,
    this.hintText = 'Type a message',
    this.keyboardAppearance,
    this.autocorrect,
    this.autofocus = false,
    this.textCapitalization = TextCapitalization.sentences,
    this.keyboardType,
    this.textInputAction = TextInputAction.newline,
    this.focusNode,
    this.maxLength,
    this.minLines = 1,
    this.maxLines = 3,
    this.bottomWidget,
  });

  @override
  State<Composer> createState() => _ComposerState();
}

class _ComposerState extends State<Composer>
    with SingleTickerProviderStateMixin {
  final _key = GlobalKey();
  late final TextEditingController _textController;
  late final FocusNode _focusNode;
  late final ComposerHeightNotifier _heightNotifier;
  late final BottomPanelTypeChangeNotifier _panelTypeNotifier;
  late final AnimationController _animationController;
  late final Animation<Offset> _slideAnimation;

  @override
  void initState() {
    super.initState();
    _textController = widget.textEditingController ?? TextEditingController();
    _focusNode = widget.focusNode ?? FocusNode();
    _focusNode.onKeyEvent = _handleKeyEvent;
    _heightNotifier = context.read<ComposerHeightNotifier>();
    _panelTypeNotifier = context.read<BottomPanelTypeChangeNotifier>();

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );

    _slideAnimation = Tween<Offset>(
      begin: const Offset(0, 1),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ));

    _panelTypeNotifier.addListener(_handlePanelTypeChange);
    _focusNode.addListener(_handleFocusChange);
    WidgetsBinding.instance.addPostFrameCallback((_) => _measure());
  }

  KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) {
    // Check for Shift+Enter
    if (event is KeyDownEvent &&
        event.logicalKey == LogicalKeyboardKey.enter &&
        HardwareKeyboard.instance.isShiftPressed) {
      _handleSubmitted(_textController.text);
      return KeyEventResult.handled;
    }
    return KeyEventResult.ignored;
  }

  void _handleSubmitted(String text) {
    if (text.trim().isEmpty) return;

    final onMessageSend = context.read<OnMessageSendCallback?>();
    if (onMessageSend != null) {
      onMessageSend(text);
      _textController.clear();
    }
  }

  void _handleFocusChange() {
    if (_focusNode.hasFocus) {
      // 当输入框获得焦点时，切换到键盘状态
      _panelTypeNotifier.setPanelType(BottomPanelType.keyboard);
    } else if (_panelTypeNotifier.panelType == BottomPanelType.keyboard) {
      // 当输入框失去焦点且当前是键盘状态时，切换到无状态
      _panelTypeNotifier.setPanelType(BottomPanelType.none);
    }
  }

  void _handlePanelTypeChange() {
    switch (_panelTypeNotifier.panelType) {
      case BottomPanelType.keyboard:
        _animationController.reverse();
        if (!_focusNode.hasFocus) {
          _focusNode.requestFocus();
        }
        break;
      case BottomPanelType.panel:
        _animationController.forward();
        if (_focusNode.hasFocus) {
          _focusNode.unfocus();
        }
        break;
      case BottomPanelType.none:
        _animationController.reverse();
        if (_focusNode.hasFocus) {
          _focusNode.unfocus();
        }
        break;
    }
  }

  @override
  void didUpdateWidget(covariant Composer oldWidget) {
    super.didUpdateWidget(oldWidget);
    WidgetsBinding.instance.addPostFrameCallback((_) => _measure());
  }

  @override
  void dispose() {
    if (widget.textEditingController == null) {
      _textController.dispose();
    }
    if (widget.focusNode == null) {
      _focusNode.dispose();
    }
    _panelTypeNotifier.removeListener(_handlePanelTypeChange);
    _focusNode.removeListener(_handleFocusChange);
    _animationController.dispose();
    super.dispose();
  }

  List<ComposerAction> _getDefaultLeftActions() {
    final onAttachmentTap = context.read<OnAttachmentTapCallback?>();
    if (onAttachmentTap == null) return [];

    return [
      ComposerAction.defaultAttachment(
        onTap: onAttachmentTap,
      ),
    ];
  }

  List<ComposerAction> _getDefaultRightActions() {
    return [
      ComposerAction.defaultSend(
        onTap: () => _handleSubmitted(_textController.text),
      ),
    ];
  }

  Widget _buildActionButton(ComposerAction action) {
    return GestureDetector(
      child: action.icon,
      onTap: () {
        if (action.type == ComposerActionType.send) {
          _handleSubmitted(_textController.text);
        }
        if (action.type == ComposerActionType.panel) {
          _panelTypeNotifier.setPanelType(BottomPanelType.panel);
        }
        action.onTap?.call();
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    final bottomSafeArea = widget.handleSafeArea == true
        ? MediaQuery.of(context).padding.bottom
        : 0.0;
    final theme = context.watch<ChatTheme>();

    final leftActions = widget.leftActions ?? _getDefaultLeftActions();
    final rightActions = widget.rightActions ?? _getDefaultRightActions();

    return Positioned(
      left: widget.left,
      right: widget.right,
      top: widget.top,
      bottom: widget.bottom,
      child: ClipRect(
        child: Container(
          key: _key,
          color: widget.backgroundColor ?? theme.colors.surfaceContainerLow,
          child: Column(
            children: [
              if (widget.topWidget != null) widget.topWidget!,
              Padding(
                padding: widget.handleSafeArea == true
                    ? (widget.padding?.add(
                  EdgeInsets.only(bottom: bottomSafeArea),
                ) ??
                    EdgeInsets.only(bottom: bottomSafeArea))
                    : (widget.padding ?? EdgeInsets.zero),
                child: Row(
                  children: [
                    ...leftActions.map((action) => _buildActionButton(action)),
                    SizedBox(width: widget.gap),
                    Expanded(
                      child: TextField(
                        controller: _textController,
                        decoration: InputDecoration(
                          hintText: widget.hintText,
                          hintStyle: theme.typography.bodyMedium.copyWith(
                            color: widget.hintColor ??
                                theme.colors.onSurface.withOpacity(0.5),
                          ),
                          border: widget.inputBorder,
                          filled: widget.filled,
                          fillColor: widget.inputFillColor ??
                              theme.colors.surfaceContainerHigh,
                          contentPadding: const EdgeInsets.symmetric(
                            horizontal: 16,
                            vertical: 8,
                          ),
                        ),
                        style: theme.typography.bodyMedium.copyWith(
                          color: widget.textColor ?? theme.colors.onSurface,
                        ),
                        keyboardAppearance: widget.keyboardAppearance,
                        autocorrect: widget.autocorrect ?? true,
                        autofocus: widget.autofocus,
                        textCapitalization: widget.textCapitalization,
                        keyboardType: widget.keyboardType,
                        textInputAction: widget.textInputAction,
                        focusNode: _focusNode,
                        maxLength: widget.maxLength,
                        minLines: widget.minLines,
                        maxLines: widget.maxLines,
                      ),
                    ),
                    SizedBox(width: widget.gap),
                    ...rightActions.map((action) => _buildActionButton(action)),
                  ],
                ),
              ),
              // bottomWidget 显示逻辑
              if (widget.bottomWidget != null)
                SlideTransition(
                  position: _slideAnimation,
                  child: Consumer<BottomPanelTypeChangeNotifier>(
                    builder: (context, notifier, child) {
                      return AnimatedSwitcher(
                        duration: const Duration(milliseconds: 200),
                        child: notifier.panelType == BottomPanelType.panel
                            ? widget.bottomWidget!
                            : const SizedBox.shrink(),
                      );
                    },
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  void _measure() {
    final context = _key.currentContext;
    if (context == null) return;

    final height = context.size?.height ?? 0;
    _heightNotifier.setHeight(height);
  }
}